package method;

/**
 * @author yuisama
 * @date 2022/08/20 09:57
 * 递归函数
 **/
public class MethodRecursion {
    public static void main(String[] args) {
//        int n = 5;
//        System.out.println(factor(n));
//        System.out.println(add(n));
        // 19
//        System.out.println(sum(1729));
//        // 15
//        System.out.println(sum(12345));
//        print(1234);
//        System.out.println();
//        print(1729);
//        System.out.println();
//        print(12345);
//        System.out.println();
//        printReverse(1234);
//        System.out.println();
//        printReverse(1729);
//        System.out.println();
//        printReverse(12345);
//        System.out.println(fibo(6));
//        System.out.println(fibo(7));
//        System.out.println(fibo(8));
        System.out.println("开始计算48的斐波那契数");
        long start = System.nanoTime();
        System.out.println(fiboNonRecursion(48));
        long end = System.nanoTime();
        System.out.println("计算结束，共耗时 : " + (end - start) / 1000000.0 + "ms");
    }

    /**
     * 循环求解fibo数
     * @param num
     * @return
     */
    public static int fiboNonRecursion(int num) {
        // 倒数第二项
        int last2 = 1;
        // 倒数第一项
        int last1 = 1;
        // 当前项
        int cur = 0;
        for (int i = 3; i <= num; i++) {
            cur = last1 + last2;
            last2 = last1;
            last1 = cur;
        }
        return cur;
    }

    /**
     * 递归实现斐波那契数
     * 传入一个正整数n，就能求出其对应的斐波那契数
     * n => 5  => 5 ,n = 6 > 8
     * @param n 项数
     * @return
     */
    public static int fibo(int n) {
        // 1.边界
        if (n == 1 || n == 2) {
            return 1;
        }
        // 此时n >=3
        return fibo(n - 1) + fibo(n - 2);
    }

    /**
     * 传入任意一个非负整数num，就能按照从低位到高位的依次输出
     * eg : 1729 => 9 2 7 1
     * 12345 => 5 4 3 2 1
     * @param num
     */
    public static void printReverse(int num) {
        // 1.边界
        if (num < 10) {
            System.out.print(num + " ");
            return;
        }
        // 2.当前num一定至少是个十位数，当前已知就是个位是多少，num % 10
        System.out.print(num % 10 + " ");
        // 3.从十位到最高位的输出，交个另外一个好心人 printReverse(num / 10);
        printReverse(num / 10);
    }

    /**
     * 传入任意一个整数，就能按照其位数由高到底依次输出其每一位的数字！
     * num = 1234  => 1 2 3 4
     * @param num
     */
    public static void print(int num) {
        // 1.边界
        if (num < 10) {
            System.out.print(num + " ");
            return;
        }
        print(num / 10);
        // 此时其他位数的输出已经结束了，该输出个位
        System.out.print(num % 10 +" ");
    }

    /**
     * 传入任意一个非负整数n，就能求出组成n的各个位数之和
     * 当n = 1729，组成n的各个位数之和 = 1 + 7 + 2 + 9 = 19
     * @param n
     * @return
     */
    public static int sum(int n) {
        // 1.边界条件
        if (n < 10) {
            return n;
        }
        // 说明此时n至少是个十位数 n >= 10 我已知的就是个位是多少 n % 10 就是个位，剩下位数之和交给别的函数sum(n/10)帮我做
        return n % 10 + sum(n / 10);
    }

    /**
     * 传入一个整数n，就能求出从1 + 2 + 3 + 4 +... + n的值
     * @param n
     * @return
     */
    public static int add(int n) {
        // 1.边界,不需要任何额外计算立即可以求得的值
        if (n == 1) {
            return 1;
        }
        // n >= 2,已知只知道当前数n是多少 sum = n + sum(n - 1)
        return n + add(n - 1);
    }

    /**
     * a.抓语义 - 传入一个正整数n，就能求出他的阶乘值并返回
     * 假设此时这个函数别人已经帮我写好了，我只需要思考如何利用好这个函数帮助我来解决问题
     * b.找终止
     * @param n
     * @return
     */
    public static int factor(int n) {
        // 1.边界条件
        if (n <= 2) {
            return n;
        }
        int ret = n * factor(n - 1);
        return ret;
    }
}